#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#define MAX_CLIENTS 10
#define BUFFER_SIZE 1024

typedef struct {
    int sockfd;
    struct sockaddr_in addr;
    char ip[INET_ADDRSTRLEN];
    int port;
    char username[BUFFER_SIZE];
} Client;

Client clients[MAX_CLIENTS];
int client_count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *handle_client_accept();

void send_to_all_clients(const char* message) {
    pthread_mutex_lock(&mutex);
    for (int i = 0; i < client_count; i++) {
        if (clients[i].sockfd != 0) {
            send(clients[i].sockfd, message, strlen(message), 0);
        }
    }
    pthread_mutex_unlock(&mutex);
}

void *handle_client(void *arg) {
    int client_sockfd = *((int *)arg);
    free(arg);
    char buffer[BUFFER_SIZE];
    int bytes_received;

    // 接收用户名
    bytes_received = recv(client_sockfd, buffer, BUFFER_SIZE - 1, 0);
    if (bytes_received > 0) {
        buffer[bytes_received] = '\0';
        pthread_mutex_lock(&mutex);
        for (int i = 0; i < MAX_CLIENTS; i++) {
            if (clients[i].sockfd == 0) {
                clients[i].sockfd = client_sockfd;
                if (getpeername(client_sockfd, (struct sockaddr *)&clients[i].addr, (socklen_t *)&clients[i].port) == -1) {
                    perror("getpeername");
                }
                inet_ntop(AF_INET, &(clients[i].addr.sin_addr), clients[i].ip, INET_ADDRSTRLEN);
                clients[i].port = ntohs(clients[i].addr.sin_port);
                strcpy(clients[i].username, buffer);
                client_count++;
                printf("客户端 %s:%d（用户名：%s）已连接\n", clients[i].ip, clients[i].port, clients[i].username);
                break;
            }
        }
        pthread_mutex_unlock(&mutex);
    }

    // 初始发送在线用户
    char online_users[BUFFER_SIZE] = "当前在线用户：\n";
    pthread_mutex_lock(&mutex);
    for (int i = 0; i < MAX_CLIENTS; i++) {
        if (clients[i].sockfd != 0) {
            sprintf(buffer, "%s\n", clients[i].username);
            strcat(online_users, buffer);
        }
    }
    pthread_mutex_unlock(&mutex);
    send(client_sockfd, online_users, strlen(online_users), 0);

    while ((bytes_received = recv(client_sockfd, buffer, BUFFER_SIZE - 1, 0)) > 0) {
        buffer[bytes_received] = '\0';

        if (strcmp(buffer, "GET_ONLINE_USERS") == 0) {
            char user_list[BUFFER_SIZE] = "当前在线用户：\n";
            pthread_mutex_lock(&mutex);
            for (int i = 0; i < MAX_CLIENTS; i++) {
                if (clients[i].sockfd != 0) {
                    sprintf(user_list + strlen(user_list), "%s\n", clients[i].username);
                }
            }
            pthread_mutex_unlock(&mutex);
            send(client_sockfd, user_list, strlen(user_list), 0);
            continue;
        }

        // 消息格式：目标用户名:消息内容
        char target_username[BUFFER_SIZE], message[BUFFER_SIZE], sender[BUFFER_SIZE];
        if (sscanf(buffer, "%[^:]:%[^\n]", target_username, message) != 2) {
            char error_msg[] = "消息格式错误，应为 目标用户名:消息内容\n";
            send(client_sockfd, error_msg, strlen(error_msg), 0);
            continue;
        }

        pthread_mutex_lock(&mutex);

        // 获取发送者用户名
        strcpy(sender, "未知");
        for (int j = 0; j < MAX_CLIENTS; j++) {
            if (clients[j].sockfd == client_sockfd) {
                strcpy(sender, clients[j].username);
                break;
            }
        }

        // 发送给目标用户
        int found = 0;
        for (int i = 0; i < MAX_CLIENTS; i++) {
            if (clients[i].sockfd != 0 && strcmp(clients[i].username, target_username) == 0) {
                char full_msg[BUFFER_SIZE];
                snprintf(full_msg, BUFFER_SIZE, "%s: %s", sender, message);
                send(clients[i].sockfd, full_msg, strlen(full_msg), 0);
                found = 1;
                break;
            }
        }

        if (!found) {
            char not_found_msg[] = "目标客户端未找到\n";
            send(client_sockfd, not_found_msg, strlen(not_found_msg), 0);
        }

        pthread_mutex_unlock(&mutex);
    }

    // 客户端断开
    if (bytes_received == 0) {
        pthread_mutex_lock(&mutex);
        for (int i = 0; i < MAX_CLIENTS; i++) {
            if (clients[i].sockfd == client_sockfd) {
                printf("客户端 %s:%d（用户名：%s）已断开连接\n", clients[i].ip, clients[i].port, clients[i].username);
                clients[i].sockfd = 0;
                break;
            }
        }
        pthread_mutex_unlock(&mutex);
    } else if (bytes_received == -1) {
        perror("recv");
    }

    close(client_sockfd);
    pthread_exit(NULL);
}

void show_server_menu() {
    printf("\n--- 局域网聊天室服务器菜单 ---\n");
    printf("1. 发布公告\n");
    printf("2. 查看在线用户\n");
    printf("3. 退出\n");
    printf("请输入你的选择: ");
}

int main() {
    int res = 0;
    int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    int opt = 1;
    setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    res = bind(server_socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (res == -1) {
        perror("bind");
        return 1;
    }

    res = listen(server_socket_fd, MAX_CLIENTS);
    if (res == -1) {
        perror("listen");
        return 1;
    }

    printf("服务器启动，监听端口8080...\n");

    pthread_t accept_thread;
    pthread_create(&accept_thread, NULL, handle_client_accept, &server_socket_fd);

    int choice;
    char buffer[BUFFER_SIZE];
    while (1) {
        show_server_menu();
        if (scanf("%d", &choice) != 1) {
            while (getchar() != '\n');
            printf("输入无效，请输入一个有效的数字。\n");
            continue;
        }
        while (getchar() != '\n');

        switch (choice) {
            case 1:
                printf("请输入公告内容：");
                if (fgets(buffer, BUFFER_SIZE - 1, stdin) == NULL) {
                    perror("fgets");
                    continue;
                }
                buffer[strcspn(buffer, "\n")] = '\0';
                send_to_all_clients(buffer);
                break;
            case 2:
                printf("当前在线用户：\n");
                pthread_mutex_lock(&mutex);
                for (int i = 0; i < MAX_CLIENTS; i++) {
                    if (clients[i].sockfd != 0) {
                        printf("%s:%d （用户名：%s）\n", clients[i].ip, clients[i].port, clients[i].username);
                    }
                }
                pthread_mutex_unlock(&mutex);
                break;
            case 3:
                printf("正在退出...\n");
                pthread_mutex_lock(&mutex);
                for (int i = 0; i < MAX_CLIENTS; i++) {
                    if (clients[i].sockfd != 0) {
                        close(clients[i].sockfd);
                    }
                }
                pthread_mutex_unlock(&mutex);
                close(server_socket_fd);
                pthread_mutex_destroy(&mutex);
                return 0;
            default:
                printf("无效的选择，请重新输入。\n");
        }
    }

    return 0;
}

void *handle_client_accept(void *arg) {
    int server_socket_fd = *((int *)arg);
    struct sockaddr_in client_addr;
    socklen_t len = sizeof(client_addr);

    while (1) {
        int *client_sockfd = malloc(sizeof(int));
        *client_sockfd = accept(server_socket_fd, (struct sockaddr *)&client_addr, &len);
        if (*client_sockfd == -1) {
            perror("accept");
            free(client_sockfd);
            continue;
        }

        pthread_t tid;
        pthread_create(&tid, NULL, handle_client, client_sockfd);
        pthread_detach(tid);
    }

    pthread_exit(NULL);
}
